package com.leyou.order.task;

import com.leyou.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @package com.leyou.order.task
 * @description: 定时任务清理过期未支付订单
 * @author: 许超越
 * @date 2019/7/15 20:13
 * @version: V1.0
 */
@Component
@Slf4j
public class CloseOrderTask {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private OrderService orderService;

    /**
     * 定时任务的频率，30分钟
     */
    private static final long TASK_INTERVAL = 1800000;
    /**
     * 定时任务的锁自动释放时间一般只要大于各服务器的时钟飘移时长+任务执行时长即可,此处默认120秒
     */
    private static final long TASK_LEASE_TIME = 180;
    /**
     * 订单超时的期限，1小时，单位s
     */
    private static final int OVERDUE_SECONDS = 3600;
    /**
     * 锁的名称
     */
    private static final String LOCK_KEY = "close:order:task:lock";

    @Scheduled(fixedDelay = TASK_INTERVAL)
    public void closeOrder() {
        //1.创建锁对象
        RLock lock = redissonClient.getLock(LOCK_KEY);
        try {
            //2.获取锁
            boolean isLock = lock.tryLock(0, TASK_LEASE_TIME, TimeUnit.SECONDS);
            if (!isLock) {
                log.info("【清理订单任务】未能获取任务锁，结束任务。");
                //获取锁失败提前结束
                return;
            }
            //2.开始执行任务
            try {
                //2.1计算订单清理截止时间
                Date deadline = DateTime.now().minusSeconds(OVERDUE_SECONDS).toDate();
                //2.2清理订单
                orderService.closeOverdueOrders(deadline);
            } finally {
                //3.任务结束释放锁
                lock.unlock();
                log.info("【清理订单任务】任务执行完毕，释放锁。");
            }
        } catch (InterruptedException e) {
            log.error("【清理订单任务】获取任务锁异常，原因：{}", e.getMessage(), e);
        }
    }
}
